package com.woshengqile.cfg;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import net.hasor.plugins.jfinal.HasorInterceptor;
import net.hasor.plugins.jfinal.HasorPlugin;

import org.apache.commons.lang.StringUtils;

import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.util.JdbcConstants;
import com.alibaba.druid.wall.WallFilter;
import com.jfinal.config.Constants;
import com.jfinal.config.Handlers;
import com.jfinal.config.Interceptors;
import com.jfinal.config.JFinalConfig;
import com.jfinal.config.Plugins;
import com.jfinal.config.Routes;
import com.jfinal.core.Controller;
import com.jfinal.core.JFinal;
import com.jfinal.ext.route.AutoBindRoutes;
import com.jfinal.kit.PropKit;
import com.jfinal.plugin.activerecord.ActiveRecordPlugin;
import com.jfinal.plugin.activerecord.CaseInsensitiveContainerFactory;
import com.jfinal.plugin.cron4j.Cron4jPlugin;
import com.jfinal.plugin.druid.DruidPlugin;
import com.jfinal.plugin.druid.DruidStatViewHandler;
import com.jfinal.plugin.druid.IDruidStatViewAuth;
import com.jfinal.render.FreeMarkerRender;
import com.jfinal.render.ViewType;
import com.jfinal.template.Engine;
import com.woshengqile.CommonAttributes;
import com.woshengqile.api.interceptor.ErrorInterceptor;
import com.woshengqile.cache.J2CachePlugin;
import com.woshengqile.interceptor.CsrfInterceptor;
import com.woshengqile.model._MappingKit;
import com.woshengqile.security.MyJdbcAuthzService;
import com.woshengqile.shiro.core.ShiroInterceptor;
import com.woshengqile.shiro.core.ShiroPlugin;
import com.woshengqile.shiro.core.SubjectKit;
import com.woshengqile.shiro.freemarker.ShiroTags;
import com.woshengqile.sqlinxml.SqlInXmlPlugin;
import com.woshengqile.template.directive.FlashMessageDirective;
import com.woshengqile.template.directive.PaginationDirective;
import com.woshengqile.template.method.AbbreviateMethod;
import com.woshengqile.template.method.CurrencyMethod;
import com.woshengqile.template.method.MessageMethod;
import com.woshengqile.util.SystemUtils;

import freemarker.ext.beans.BeansWrapper;
import freemarker.template.Configuration;
import freemarker.template.TemplateModelException;
import freemarker.template.utility.StandardCompress;

public class JFinalProjectConfig extends JFinalConfig {

	/**
	 * 供Shiro插件使用。
	 */
	Routes routes;
	
	@Override
	public void configConstant(Constants constants) {
		PropKit.use(CommonAttributes.JFINALSHOP_PROPERTIES_PATH);
		constants.setDevMode(PropKit.getBoolean("devMode", false));
		constants.setViewType(ViewType.FREE_MARKER);
		constants.setI18nDefaultBaseName("i18n");
		constants.setI18nDefaultLocale("zh_CN");
		constants.setViewExtension(".ftl");
		constants.setError401View("/common/error/not_found.ftl");
		constants.setError403View("/common/error/unauthorized.ftl");
		constants.setError404View("/common/error/not_found.ftl");
		constants.setError500View("/common/error/not_found.ftl");
	}

	@Override
	public void configRoute(Routes routes) {
		this.routes = routes;
		
		AutoBindRoutes abr = new AutoBindRoutes();
		// 忽略不自动扫描的Controller
		List<Class<? extends Controller>> clazzes = new ArrayList<Class<? extends Controller>>();
		clazzes.add(com.woshengqile.controller.admin.BaseController.class);
		clazzes.add(com.woshengqile.api.controller.BaseAPIController.class);
		abr.addExcludeClasses(clazzes);
		routes.add(abr);
	}

	@Override
	public void configEngine(Engine me) {
		
	}

	@Override
	public void configPlugin(Plugins plugins) {
//		String publicKey = StringUtils.trim(PropKit.get("jdbc.publicKey")); 
//		String password = StringUtils.trim(PropKit.get("jdbc.password"));
		
		//配置druid连接池
		DruidPlugin druidDefault = new DruidPlugin(
		StringUtils.trim(PropKit.get("jdbc.url")), 
		StringUtils.trim(PropKit.get("jdbc.username")),
//		EncriptionKit.passwordDecrypt(publicKey, password),
		StringUtils.trim(PropKit.get("jdbc.password")),
		StringUtils.trim(PropKit.get("jdbc.driver")));
		// StatFilter提供JDBC层的统计信息
		druidDefault.addFilter(new StatFilter());

		// WallFilter的功能是防御SQL注入攻击
		WallFilter wallDefault = new WallFilter();

		wallDefault.setDbType(JdbcConstants.MYSQL);
		druidDefault.addFilter(wallDefault);
		
		druidDefault.setInitialSize(PropKit.getInt("connection_pools.initial_pool_size"));
		druidDefault.setMaxPoolPreparedStatementPerConnectionSize(PropKit.getInt("connection_pools.max_pool_size"));
		druidDefault.setTimeBetweenConnectErrorMillis(PropKit.getInt("connection_pools.checkout_timeout"));
		plugins.add(druidDefault);

		// 配置ActiveRecord插件
		ActiveRecordPlugin arp = new ActiveRecordPlugin(druidDefault);
		plugins.add(arp);
		
		// 配置属性名(字段名)大小写不敏感容器工厂
		arp.setContainerFactory(new CaseInsensitiveContainerFactory());
		
		// 显示SQL
		arp.setShowSql(PropKit.getBoolean("isShowSql", false));
		
		
		// 所有配置在 MappingKit
		_MappingKit.mapping(arp);
		
		//Ehcache缓存
		//plugins.add(new EhCachePlugin());
		plugins.add(new J2CachePlugin());
		
		// 定时插件
		plugins.add(new Cron4jPlugin("cron4j.properties"));
		
		//shiro权限框架，添加到plugin
		plugins.add(new ShiroPlugin(routes, new MyJdbcAuthzService()));
		
		//（必选）Hasor 框架的启动和销毁
		plugins.add(new HasorPlugin(JFinal.me()));
		
		// sql语句plugin
		plugins.add(new SqlInXmlPlugin());
	}

	@Override
	public void configInterceptor(Interceptors me) {
		// 依赖注入
        me.add(new HasorInterceptor(JFinal.me()));
        // CSRF拦截器
        me.add(new CsrfInterceptor());
		// 添加shiro
        me.add(new ShiroInterceptor());
        // 捕获所有异常
        me.add(new ErrorInterceptor());
	}

	@Override
	public void configHandler(Handlers handlers) {
		DruidStatViewHandler dvh = new DruidStatViewHandler("/druid", new IDruidStatViewAuth() {
			@Override
			public boolean isPermitted(HttpServletRequest request) {
				if (SubjectKit.hasRoleAdmin()) {
					return true;
				} else {
					return false;
				}
			}
		});
		handlers.add(dvh);
	}

	@Override
	public void afterJFinalStart() {
		try {
			Configuration cfg = FreeMarkerRender.getConfiguration();
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("base", JFinal.me().getContextPath());
			map.put("showPowered", StringUtils.trim(PropKit.get("show_powered")));
			map.put("setting", SystemUtils.getSetting());
			map.put("message", new MessageMethod());
			map.put("abbreviate", new AbbreviateMethod());
			map.put("currency", new CurrencyMethod());
			map.put("flash_message", new FlashMessageDirective());
			map.put("pagination", new PaginationDirective());
			map.put("compress", StandardCompress.INSTANCE);
			cfg.setSharedVaribles(map);
			
			cfg.setDefaultEncoding(StringUtils.trim(PropKit.get("template.encoding")));
			cfg.setURLEscapingCharset(StringUtils.trim(PropKit.get("url_escaping_charset")));
			cfg.setTemplateUpdateDelayMilliseconds(PropKit.getLong(("template.update_delay")));
			cfg.setTagSyntax(Configuration.SQUARE_BRACKET_TAG_SYNTAX);
			cfg.setClassicCompatible(true);
			cfg.setNumberFormat(StringUtils.trim(PropKit.get("template.number_format")));
			cfg.setBooleanFormat(StringUtils.trim(PropKit.get("template.boolean_format")));
			cfg.setDateTimeFormat(StringUtils.trim(PropKit.get("template.datetime_format")));
			cfg.setDateFormat(StringUtils.trim(PropKit.get("template.date_format")));
			cfg.setTimeFormat(StringUtils.trim(PropKit.get("template.time_format")));
			cfg.setObjectWrapper(new BeansWrapper(Configuration.VERSION_2_3_26));
			cfg.setWhitespaceStripping(true);
			cfg.setSharedVariable("shiro", new ShiroTags());
			cfg.setServletContextForTemplateLoading(JFinal.me().getServletContext(), StringUtils.trim(PropKit.get("template.loader_path")));
			super.afterJFinalStart();
		} catch (TemplateModelException e) {
			e.printStackTrace();
		}
	}

}
